home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / printing / pdlog expand / pdlog expand.c next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  19.7 KB  |  679 lines

  1. /*
  2.     File:        PDlog Expand.c
  3.  
  4.     Contains:    This example shows how to add items to print dialogs.  It’s essentially the code 
  5.                 in Tech Note PR09, only in C.  Note that in v1.0.2, a bug was corrected which is
  6.                 also in the Tech Note.
  7.                 
  8.                 NOTE: Apple reserves the top half of the screen (where the current DITL
  9.                 items are located). Applications may use the bottom half of the screen to
  10.                 add items, but should not change any items in the top half of the screen.
  11.                 An application should expand the print dialogs only as much as is
  12.                 absolutely necessary.
  13.  
  14.                 A global search and replace of 'Job' with 'Stl' will produce code that
  15.                 modifies the style dialog.
  16.                 • Another NOTE: As of System 7.5.3, neither our Append_DITL nor the system version
  17.                 handles appending of 'ictb' or 'dctb's correctly. This is a bug that's planned to be
  18.                 fixed in the future, but I'm warning you about it here. <davep>
  19.                 
  20.     Written by: Dave Hersey    
  21.  
  22.     Copyright:    Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
  23.  
  24.                 You may incorporate this Apple sample source code into your program(s) without
  25.                 restriction. This Apple sample source code has been provided "AS IS" and the
  26.                 responsibility for its operation is yours. You are not permitted to redistribute
  27.                 this Apple sample source code as "Apple sample source code" after having made
  28.                 changes. If you're going to re-distribute the source, we require that you make
  29.                 it clear in the source that the code was descended from Apple sample source
  30.                 code, but that you've made changes.
  31.  
  32.     Change History (most recent first):
  33.                 3/10/2000    DavidH            Removed a number of possible memory leaks in error handling code.
  34.                 7/26/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  35.                 9/3/96        davep            Change list handling to match recommendations of
  36.                                              LW8 engineering.
  37.                 8/21/96        mxm                Added the list for a sample
  38.                 6/10/96        davep            Use the OS's AppendDITL if it's there. Add balloon help.
  39.                 11/16/95    davep            updated to use CallPItemProc() and PItemUPP. Make it fully
  40.                                              ANSI.    Explicitly include needed headers, so back-port to 
  41.                                              MPW is easier.
  42.                 6/20/95        njvt            updated for Universal Headers and MWC-PPC 
  43.                 9/29/93        dmh                fixed bug in Append_DITL (also in TN #95) which appends 2 extra bytes.
  44.                 2/25/92        dmh                fixed lack of print handle tossing and added something to print.     
  45. */
  46.  
  47. #include <Printing.h>
  48. #include <Dialogs.h>
  49. #include <Gestalt.h>
  50. #include <MixedMode.h>
  51. #include <SegLoad.h>
  52. #include <Resources.h>
  53. #include <ToolUtils.h>
  54. #include <Fonts.h>
  55. #include <Lists.h>
  56.  
  57. static TPPrDlg PrtJobDialog;    /* pointer to job dialog */
  58.  
  59. /* 
  60.  
  61. This points to the following structure:
  62.  
  63. struct TPrDlg {
  64.     DialogRecord                    Dlg;                        // The Dialog window
  65.     ModalFilterUPP                    pFltrProc;                    // The Filter Proc.
  66.     PItemUPP                        pItemProc;                    // The Item evaluating proc.
  67.     THPrint                            hPrintUsr;                    // The user's print record.
  68.     Boolean                            fDoIt;
  69.     Boolean                            fDone;
  70.     long                            lUser1;                        // Four longs for apps to hang global data.
  71.     long                            lUser2;                        // Plus more stuff needed by the particular
  72.     long                            lUser3;                        // printing dialog.
  73.     long                            lUser4;
  74. };
  75. typedef struct TPrDlg TPrDlg;
  76. typedef TPrDlg *TPPrDlg;
  77. typedef TPPrDlg TPPrDlgRef;
  78.  
  79. */
  80.  
  81. /* Declare ‘pascal’ functions and procedures */
  82.  
  83. extern short    Append_DITL(TPPrDlg, short);        /* Our AppendDITL function.            */
  84. extern pascal    TPPrDlg MyJobDlgInit(THPrint);        /* Our extention to PrJobInit.        */
  85. extern pascal    void MyJobItems(TPPrDlg, short);    /* Our modal item handler.            */
  86. extern OSErr    Print(void);
  87. pascal void MyListDraw(WindowPtr theWindow, short itemNo); //mxm
  88.  
  89. #define MyDITL 256    /* resource ID of my DITL to be spliced onto job dialog */
  90. #define kPanePopUp (6)            /* mxm */
  91.  
  92. ListHandle     gList = nil;                 /* mxm */
  93. UserItemUPP    myDrawListUPP = nil;         /* mxm */
  94.  
  95. THPrint hPrintRec;    /* handle to print record */
  96. long prFirstItem;    /* save our first item here */
  97. PItemUPP prPItemProc;    /* we need to store the old itemProc here */
  98.  
  99. /*-----------------------------------------------------------------------*/
  100.     WindowPtr    MyWindow;
  101.     OSErr    err;
  102.     Str255    myStr;
  103.  
  104. #if PRAGMA_ALIGN_SUPPORTED
  105. #pragma options align=mac68k
  106. #endif
  107.  
  108. typedef struct dialog_item_struct {
  109.     Handle    handle;    /* handle or procedure pointer for this item */
  110.     Rect    bounds;    /* display rectangle for this item */
  111.     char    type;    /* item type - 1 */
  112.     char    data[1];    /* length byte of data */
  113. } DialogItem, *DialogItemPtr, **DialogItemHandle;
  114.  
  115. typedef struct append_item_list_struct {
  116.     short    max_index; /* number of items - 1 */
  117.     DialogItem    items[1]; /* first item in the array */
  118. } ItemList, *ItemListPtr, **ItemListHandle;
  119.  
  120. typedef union signed_byte_union {
  121.     short    integer;
  122.     char    bytes[2];
  123. } ByteAccess;
  124.  
  125.  
  126. static Boolean append_exits(void);
  127. static Boolean append_exits(void)
  128. {
  129.     long    response;
  130.  
  131.     if (Gestalt(gestaltDITLExtAttr,&response) == noErr) {
  132.         return !!(response & (1 << gestaltDITLExtPresent));
  133.     } else {
  134.         return false;    /* simple-minded, but hey, so am I. -DaveP */
  135.     }
  136. }
  137.  
  138.  
  139. /*    This routine appends all of the items of a specified DITL    */
  140. /*    onto the end of a specified DLOG — We don’t even need to know the format    */
  141. /*    of the DLOG    */
  142.  
  143. /*    this will be done in 3 steps:    */
  144. /*    1. append the items of the specified DITL onto the existing DLOG    */
  145. /*    2. expand the original dialog window as required    */
  146. /*    3. return the adjusted number of the first new user item    */
  147.  
  148. short Append_DITL(TPPrDlg dialog, short item_list_ID)
  149. {
  150.     ItemListHandle     append_item_list;    /* handle to DITL being appended */
  151.     ItemListHandle    dlg_item_list;    /* handle to DLOG's item list */
  152.     short            first_item;
  153.  
  154.     dlg_item_list = (ItemListHandle)((DialogPeek)dialog)->items;
  155.     first_item = (**dlg_item_list).max_index + 2;
  156.  
  157.     append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
  158.     if ( append_item_list == NULL ) {
  159.         DebugStr("\pError loading DITL resource");
  160.         return first_item;
  161.     }
  162.  
  163.     if (append_exits()) {
  164.         AppendDITL((DialogPtr)dialog, (Handle) append_item_list, appendDITLBottom);
  165.         
  166.         /* Make sure to release the DITL resource before returning */
  167.         ReleaseResource( (Handle)append_item_list );
  168.         return first_item;
  169.     } else {
  170.         Point       offset;
  171.         Rect        max_rect;
  172.         DialogItemPtr   item;   /* pointer to item being appended */
  173.         short       new_items, data_size, i;
  174.         ByteAccess  usb;
  175.         OSErr       err;
  176.  
  177.     /*
  178.         Using the original DLOG
  179.      
  180.         1. Remember the original window Size.
  181.         2. Set the offset Point to be the bottom of the original window.
  182.         3. Subtract 5 pixels from bottom and right, to be added
  183.         back later after we have possibly expanded window.
  184.         4. Get working Handle to original item list.
  185.         5. Calculate our first item number to be returned to caller.
  186.         6. Get locked Handle to DITL to be appended.
  187.         7. Calculate count of new items.
  188.     */
  189.      
  190.         if (dialog == NULL) ExitToShell();
  191.      
  192.         max_rect = ((DialogPeek)dialog)->window.port.portRect;
  193.         offset.v = max_rect.bottom;
  194.         offset.h = 0;
  195.         max_rect.bottom -= 5;
  196.         max_rect.right -= 5;
  197.      
  198.     
  199.         HLock((Handle)append_item_list);
  200.         new_items = (**append_item_list).max_index + 1;
  201.      
  202.     /*
  203.         For each item,
  204.         1. Offset the rectangle to follow the original window.
  205.         2. Make the original window larger if necessary.
  206.         3. fill in item handle according to type.
  207.     */
  208.      
  209.         item = (**append_item_list).items;
  210.         for ( i = 0; i < new_items; i++ )
  211.         {
  212.             OffsetRect(&item->bounds, offset.h, offset.v);
  213.             UnionRect(&item->bounds, &max_rect, &max_rect);
  214.             usb.integer = 0;
  215.             usb.bytes[1] = item->data[0];
  216.      
  217.             switch ( item->type & 0x7F )
  218.             {
  219.                 case ctrlItem + btnCtrl :
  220.                 case ctrlItem + chkCtrl :
  221.                 case ctrlItem + radCtrl :
  222.                     item->handle = (Handle)NewControl((DialogPtr) dialog,
  223.                         &item->bounds, (StringPtr)item->data, true,
  224.                         0, 0, 1, item->type & 0x03, 0);
  225.                 break;
  226.      
  227.                 case ctrlItem + resCtrl :
  228.                 {
  229.                     item->handle = (Handle)GetNewControl(*(short*)(item->data + 1), (DialogPtr) dialog);
  230.                     (**(ControlHandle)item->handle).contrlRect = item->bounds;
  231.                 }
  232.                 break;
  233.     
  234.                 case statText :
  235.                 case editText :
  236.                     err = PtrToHand(item->data + 1, &item->handle, usb.integer);
  237.                 break;
  238.     
  239.                 case iconItem :
  240.                     item->handle = GetIcon(*(short*)(item->data + 1));
  241.                 break;
  242.      
  243.                 case picItem :
  244.                     item->handle = (Handle)GetPicture(*(short*)(item->data + 1));
  245.                 break;
  246.      
  247.                 default :
  248.                     item->handle = NULL;
  249.             }
  250.      
  251.             data_size = (usb.integer + 1) & 0xFFFE;
  252.             item = (DialogItemPtr)((char*)item + data_size + sizeof(DialogItem));
  253.         }
  254.      
  255.      /* We need to subtract the short below because otherwise the size of the DITL count
  256.      ** gets factored in twice, and the resulting DTIL has two bytes of garbage appended
  257.      ** to it. This is a problem with the original TN#95 code as well.
  258.      */
  259.      
  260.         err = PtrAndHand((**append_item_list).items,
  261.                         (Handle)dlg_item_list,
  262.                         GetHandleSize((Handle) append_item_list)
  263.                         - sizeof(short));
  264.     
  265.         (**dlg_item_list).max_index += new_items;
  266.         HUnlock((Handle) append_item_list);
  267.         ReleaseResource((Handle) append_item_list);
  268.      
  269.         max_rect.bottom += 5;
  270.         max_rect.right += 5;
  271.         SizeWindow((WindowPtr) dialog, max_rect.right, max_rect.bottom, true);
  272.      
  273.         return first_item;
  274.     }
  275. }
  276.  
  277.  
  278. /*------------------------------------------------------------------------*/
  279.  
  280. OSErr Print(void)
  281. {
  282.     TPPrPort    pPrPort;
  283.     Rect        aRect;
  284.     TPrStatus    theStatus;
  285.     Boolean printingShouldNotProceed;
  286.     PDlgInitUPP/*PDlgInitProcPtr*/    theInitProcPtr;
  287.  
  288.     /*    Allocate a print record    */
  289.     hPrintRec = (THPrint)(NewHandle(sizeof(TPrint)));
  290.     if ( NULL == hPrintRec )
  291.     {
  292.         return iMemFullErr;
  293.     }
  294.     
  295.     /*    Fill in the default values    */
  296.     PrintDefault(hPrintRec);
  297.     
  298.     /*    Make sure the print record is valid and consistent    */
  299.     PrValidate(hPrintRec);
  300.     if (PrError() != noErr)
  301.     {
  302.         DisposeHandle( (Handle)hPrintRec );
  303.         return PrError();
  304.     }
  305.  
  306.     /* call PrJobInit to get pointer to the invisible job dialog */
  307.     PrtJobDialog = PrJobInit(hPrintRec);
  308.     if (PrError() != noErr)
  309.     {
  310.          DisposeHandle( (Handle)hPrintRec );
  311.         return PrError();
  312.     }
  313.  
  314.     /*    Create a UPP for the dialog init proc    */
  315.     theInitProcPtr = NewPDlgInitProc(MyJobDlgInit);
  316.     if ( NULL == theInitProcPtr )
  317.     {
  318.         DisposeHandle( (Handle)hPrintRec );
  319.         return iMemFullErr;
  320.     }
  321.     
  322.     /* this line does all the stuff */
  323.     printingShouldNotProceed = !PrDlgMain(hPrintRec, theInitProcPtr);
  324.  
  325.     /* Get rid of our user item draw proc mxm */
  326.     /* Allocated within MyJobDlgInit() that was called by PrDlgMain() */
  327.     if (myDrawListUPP)
  328.     {
  329.         DisposeRoutineDescriptor(myDrawListUPP);
  330.     } 
  331.  
  332.     /*    Make sure to free the InitProc UPP    */
  333.     DisposeRoutineDescriptor(theInitProcPtr);
  334.  
  335.     if (printingShouldNotProceed)
  336.     {
  337.         DisposeHandle( (Handle)hPrintRec );
  338.         return iPrAbort;
  339.     }
  340.  
  341.     if (PrError() != noErr)
  342.     {
  343.         DisposeHandle( (Handle)hPrintRec );
  344.         return PrError();
  345.     }
  346.  
  347.     /*    Open the printing document and page to prepare for drawing
  348.     **    into the printing context
  349.     */
  350.     pPrPort = PrOpenDoc(hPrintRec, NULL, NULL);
  351.     PrOpenPage(pPrPort, NULL);
  352.  
  353.     /*    Draw something on the page    */
  354.     aRect = (*hPrintRec)->prInfo.rPage;
  355.     InsetRect(&aRect, 20, 20);
  356.     PenSize(4, 4);
  357.     FrameRect(&aRect);
  358.  
  359.     /*    We're done drawing so close up the page and document    */
  360.     PrClosePage(pPrPort);
  361.     PrCloseDoc(pPrPort);
  362.  
  363.     /*    Do we need to spool the job?    */
  364.     if (!PrError() && (*hPrintRec)->prJob.bJDocLoop == bSpoolLoop)
  365.         PrPicFile(hPrintRec, NULL, NULL, NULL, &theStatus);
  366.  
  367.     /*    Don't forget to release the print record memory    */
  368.     DisposeHandle((Handle) hPrintRec);
  369.  
  370.     return(noErr);
  371. } /* Print */
  372.  
  373.  
  374. //-----------------------------------------------------------------------------
  375. pascal void MyListDraw(WindowPtr theWindow, short itemNo)
  376. //-----------------------------------------------------------------------------
  377. {
  378. #pragma unused (theWindow,itemNo)
  379.  
  380.     short    itemType;
  381.     Handle    itemH;
  382.     Rect    itemBox,r;    
  383.     Point     pt;
  384.     ControlRef cr;
  385.     RgnHandle clip = NewRgn();
  386.     
  387.     if (itemNo == kPanePopUp) {
  388.         cr = gList[0]->vScroll;
  389.         HideControl(cr);
  390.         return;
  391.     }
  392.     
  393.     GetDialogItem((DialogPtr) PrtJobDialog,itemNo,&itemType,&itemH,&itemBox);
  394.     r = theWindow->portRect;
  395.     pt.h = itemBox.left;
  396.     pt.v = itemBox.top;
  397.     cr = gList[0]->vScroll;
  398.     MoveControl(cr,itemBox.right-15,itemBox.top-1);
  399.     ShowControl(cr);
  400.     if (PtInRect(pt,&r)) {
  401.         
  402.         gList[0]->rView = itemBox;
  403.         gList[0]->rView.right -=15;  /*    inset for scroll bar    */
  404.  
  405.         ShowControl(cr);
  406.         LSetDrawingMode(true,gList);
  407.         if (clip) {
  408.             RectRgn(clip,&itemBox);
  409.             LUpdate(clip,gList);
  410.         
  411.             InsetRect(&itemBox,-1,-1);
  412.             FrameRect(&itemBox);
  413.         }
  414.     } 
  415.  
  416.     /*    Free up the region memory    */
  417.     DisposeRgn(clip);
  418. }
  419.     
  420. /*------------------------------------------------------------------------*/
  421.  
  422. pascal TPPrDlg MyJobDlgInit(THPrint hPrint)
  423. /*
  424.     this routine appends items to the standard job dialog and sets up the
  425.     user fields of the printing dialog record TPRDlg
  426.  
  427.     This routine will be called by PrDlgMain
  428. */
  429.  
  430. {
  431. #pragma unused(hPrint)
  432.  
  433.     short    firstItem;    /* first new item number */
  434.  
  435.     short    itemType, item;
  436.     Handle    itemH;
  437.     Rect    itemBox;
  438.  
  439.     firstItem = Append_DITL(PrtJobDialog, MyDITL); /* call routine to do this */
  440.  
  441.     prFirstItem = firstItem; /* save this so MyJobItems can find it */
  442.  
  443.     /* now we'll set up our DITL items -- The radio buttons */
  444.  
  445.     for (item = 5; item <= 7; item++)
  446.     {
  447.         GetDialogItem((DialogPtr) PrtJobDialog,firstItem + item -1,&itemType,&itemH,&itemBox);
  448.         SetControlValue((ControlHandle) itemH, (item == 5));
  449.     }
  450.  
  451.     /* now we'll set up the second of our DITL items -- The checkbox */
  452.  
  453.     GetDialogItem((DialogPtr) PrtJobDialog,firstItem +2,&itemType,&itemH,&itemBox);
  454.     SetControlValue((ControlHandle) itemH,1);
  455.  
  456.     
  457.     // here is the list stuff (mxm)    
  458.     {
  459.         Rect bounds ;
  460.         Point theCell = {16,200};
  461.         
  462.         
  463.         GetDialogItem((DialogPtr) PrtJobDialog,firstItem +8,&itemType,&itemH,&itemBox);
  464.  
  465.         SetRect(&bounds,0,0,1,0);
  466.         itemBox.right -=15;
  467.          
  468.         gList  = LNew(&itemBox,&bounds,theCell,0,(GrafPtr)PrtJobDialog,false,false,false,true);
  469.         if (gList) {    // this is how you need to do the scroll-bar so it'll
  470.                         // move off correctly with LaserWriter 8.4 and later
  471.                         //
  472.                         // The theory is that we have another user item which
  473.                         // has the handle for the control item for the scrollbar
  474.                         // for the list. This way, the scroll bar gets redrawn
  475.                         // in the right order, so it realises it's off the panel
  476.                         // when it is. If you don't have this code, the scroller
  477.                         // gets drawn, then the list gets moved, so you get a
  478.                         // phantom scroller in the dialog. -DaveP 9/3/96
  479.             short    scrollType;
  480.             Handle    scrollHandle;
  481.             Rect    scrollRect;
  482.             GetDialogItem((DialogPtr)PrtJobDialog,firstItem + 9, &scrollType,
  483.                 &scrollHandle, &scrollRect);
  484.             SetDialogItem((DialogPtr)PrtJobDialog,firstItem + 9, ctrlItem,
  485.                 (Handle) (**gList).vScroll, &scrollRect);
  486.         }
  487.         LAddRow(9,0,gList);
  488.         SetPt(&theCell,0,0);
  489.         // Lets add some data
  490.         LSetCell("Testing 1",9,theCell,gList);
  491.         theCell.v ++;
  492.         LSetCell("Testing 2",9,theCell,gList);
  493.         theCell.v ++;
  494.         LSetCell("Testing 3",9,theCell,gList);
  495.         theCell.v ++;
  496.         LSetCell("Testing 4",9,theCell,gList);
  497.         theCell.v ++;
  498.         LSetCell("Testing 5",9,theCell,gList);
  499.         theCell.v ++;
  500.         LSetCell("Testing 6",9,theCell,gList);
  501.         theCell.v ++;
  502.         LSetCell("Testing 7",9,theCell,gList);
  503.         theCell.v ++;
  504.         LSetCell("Testing 8",9,theCell,gList);
  505.         theCell.v ++;
  506.         LSetCell("Testing 9",9,theCell,gList);    
  507.         
  508.         LActivate(true,gList);
  509.         myDrawListUPP =  NewUserItemProc(MyListDraw);
  510.                                                                                     
  511.         SetDialogItem((DialogPtr) PrtJobDialog,firstItem + 8,itemType,(Handle)myDrawListUPP,&itemBox);
  512.                                                                         
  513.     }
  514.     
  515. /*
  516.     Now comes the part where we patch in our item handler. We have to save
  517.     the old item handler address, so we can call it if one of the standard
  518.     items is hit, and put our item handler's address in pItemProc field of
  519.     the TPrDlg struct
  520. */
  521.  
  522.     prPItemProc = PrtJobDialog->pItemProc;
  523.  
  524. /* Now we'll tell the modal item handler where our routine is */
  525.     PrtJobDialog->pItemProc = NewPItemProc(MyJobItems) ;
  526.  
  527.  
  528. /* PrDlgMain expects a pointer to the modified dialog to be returned...*/
  529.     return PrtJobDialog;
  530.  
  531. } /*myJobDlgInit*/
  532.  
  533. /*-----------------------------------------------------------------------*/
  534.  
  535.  static pascal Boolean    testFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  536. {
  537. #pragma unused(theDialog)
  538. #pragma unused(theEvent)
  539. #pragma unused(itemHit)
  540. //    DebugStr("\pMy filter proc got called");    // This gets called a lot if you uncomment it
  541.     return false;
  542. }
  543.  
  544. static pascal void testDialogUserItem(WindowPtr theWindow, short itemNo);
  545. static pascal void testDialogUserItem(WindowPtr theWindow, short itemNo)
  546. {
  547.     if (itemNo != 4) return;
  548.     else {
  549.         short    oldFont = ((GrafPtr)theWindow)->txFont;
  550.         short    oldSize = ((GrafPtr)theWindow)->txSize;
  551.         short    itemType;
  552.         Handle    h;
  553.         Rect    r;
  554.  
  555.         SetPort(theWindow);
  556.         TextFont(GetAppFont());
  557.         TextSize(9);
  558.         GetDialogItem((DialogPtr)theWindow,4,&itemType,&h,&r);
  559.         MoveTo(r.left,r.bottom);
  560.         DrawString("\pThe Pooh-snif network.");
  561.         TextFont(oldFont);
  562.         TextSize(oldSize);
  563.     }
  564. }
  565.  
  566. static void TestDialog(void);
  567. static void TestDialog(void)
  568. {
  569.     DialogPtr    theDialog = GetNewDialog(257,nil,(WindowPtr)-1L);
  570.     short    itemHit = 0;
  571.     ModalFilterUPP    mySubDialogFilterProc = nil;    // NewModalFilterProc(testFilter); // for testing
  572.     UserItemUPP        mySubDialogUserProc = NewUserItemProc(testDialogUserItem);
  573.  
  574.     {        // set up the user item to draw the outline around the ok button
  575.         short    t;
  576.         Handle    h;
  577.         Rect    r;
  578.         
  579.         GetDialogItem(theDialog,4,&t,&h,&r);
  580.         SetDialogItem(theDialog,4,t,(Handle)mySubDialogUserProc,&r);
  581.     }
  582.  
  583.     SetDialogDefaultItem(theDialog,1);
  584.     while((itemHit != 1) && (itemHit != 2)) {    // a WAY bad way of seeing if we're done, but I'm in a hurry
  585.         ModalDialog(mySubDialogFilterProc, &itemHit);
  586.     }
  587.     DisposeDialog(theDialog);
  588.     if (mySubDialogFilterProc != nil)
  589.         DisposeRoutineDescriptor(mySubDialogFilterProc);
  590.     if (mySubDialogUserProc != nil)
  591.         DisposeRoutineDescriptor(mySubDialogUserProc);
  592. }
  593.  
  594. /* here's the analogue to the SF dialog hook */
  595.  
  596. pascal void MyJobItems( TPPrDlg theDialog, short itemNo )
  597. { /* MyJobItems */
  598.     short    myItem;
  599.     short    firstItem, item, itemType, theValue;
  600.     Handle    itemH;
  601.     Rect    itemBox;
  602.  
  603.     firstItem = prFirstItem;    /* remember, we saved this in myJobDlgInit */
  604. //    DebugStr("\p Looking at the item...");
  605.     myItem = itemNo-firstItem+1;    /* "localize" current item No */
  606.     if (myItem > 0)    /* if localized item > 0, it's one of ours */
  607.     {
  608.         /* find out which of our items was hit */
  609.  
  610.         switch (myItem)
  611.         {
  612.             case 1:            /*    Static text.    */
  613.                 break;
  614.             case 2:            /*    Edit text.        */
  615.                 break;
  616.             case 3:            /*    Check box.        */
  617.                     GetDialogItem((DialogPtr) theDialog,firstItem +2,&itemType,&itemH,&itemBox);
  618.                      theValue = GetControlValue((ControlHandle) itemH);
  619.                      SetControlValue((ControlHandle) itemH, theValue != 1);
  620.                 break;
  621.             case 4:            /*    Push button.    */
  622.                 TestDialog();
  623.                 break;
  624.             case 5:            /*    Radio buttons    */
  625.             case 6:
  626.             case 7:
  627.                 for (item = 5; item <= 7; item++) {
  628.                     GetDialogItem((DialogPtr) theDialog,firstItem +item -1,&itemType,&itemH,&itemBox);
  629.                      SetControlValue((ControlHandle) itemH, item == myItem);
  630.                 }
  631.                 break;
  632.             case 8:            /*    Edit text.        */
  633.             case 9:            /*    Our List.        */ 
  634.                 {    
  635.                     Point pt;
  636.                     GetMouse(&pt);
  637.                     LClick(pt,0,gList);
  638.                 }
  639.                 break;
  640.             case 10:        /* our list's scroll bar. We don't need to do anything, but we need
  641.                             * to have some code here so we don't hit the default case */
  642.                 break;
  643.             default: Debugger(); /* OH OH */
  644.         } /* switch */
  645.     } /* if (myItem > 0) */
  646.     else /* chain to standard item handler, whose address is saved in prPItemProc */
  647.     {
  648.         CallPItemProc(prPItemProc,(DialogPtr)theDialog, itemNo);
  649.         
  650.         if (theDialog->fDone) {
  651.             // we're going away, need to clean up our scroll bar and list
  652.             if (gList) {
  653.                 (**gList).vScroll = 0L;
  654.                 LDispose(gList);
  655.             }
  656.         }
  657.     }
  658. } /* MyJobItems */
  659.  
  660.  
  661. void main(void)
  662. {
  663.     Rect    myWRect;
  664.  
  665.     InitGraf(&qd.thePort);
  666.     InitFonts();
  667.     InitWindows();
  668.     InitMenus();
  669.     InitDialogs((long)nil);
  670.     InitCursor();
  671.     SetRect(&myWRect,50,260,350,340);
  672.  
  673.     /* call the routine that does printing */
  674.     PrOpen();
  675.     err = Print();
  676.  
  677.     PrClose();
  678. } /* main */
  679.